package com.ants.boot.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 蚂蚁会花呗
 * @date 2022/1/6 16:09
 * 使用反射机制，获取树形菜单工具类
 */
public class TreeNodeUtils {

    private List<?> menuList = new ArrayList<>();

    public TreeNodeUtils(List<?> menuList) {
        this.menuList = menuList;
    }

    /**
     * 建立树形结构
     * @param idFieldName       主键、唯一键
     * @param parentIdFieldName 父键名称
     * @param parentIdVal       当值为某项时 才是父级（根）节点
     * @param listFieldName
     * @return
     */
    public List<?> buildTree(String idFieldName, String parentIdFieldName,String parentIdVal,String listFieldName) {
        try{
            List<Object> treeMenus =new ArrayList<>();
            for (Object node : getRootNode(parentIdFieldName,parentIdVal)){
                node = buildChildTree(node,idFieldName,parentIdFieldName,listFieldName);
                treeMenus.add(node);
            }
            return treeMenus;
        }catch (Exception e){
            e.printStackTrace();
            return new ArrayList<>();
        }
    }



    //递归，建立子树形结构
    private Object buildChildTree(Object node,String idFieldName, String parentIdFieldName,String listFieldName) throws NoSuchFieldException, IllegalAccessException {
        List<Object> childMenus =new  ArrayList<>();
        Class nodeClass = node.getClass();
        Field id = nodeClass.getDeclaredField(idFieldName);
        id.setAccessible(true);
        Object idValue = id.get(node);
        for (Object obj : menuList){
            Class objClazz = obj.getClass();
            Field pId = objClazz.getDeclaredField(parentIdFieldName);
            pId.setAccessible(true);
            Object pIdValue = pId.get(obj);
            if (pIdValue.toString().equals(idValue.toString())){
                childMenus.add(buildChildTree(obj,idFieldName,parentIdFieldName,listFieldName));
            }
        }
        Field children = nodeClass.getDeclaredField(listFieldName);
        if (!children.isAccessible()) {
            children.setAccessible(true);
        }
        children.set(node, childMenus);
        return node;
    }

    /**
     * 获取根节点
     * @param parentIdFieldName 父级id（根）id的字段名
     * @param parentIdVal       当值为某项时 才是父级（根）节点
     * @return
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private List<Object> getRootNode(String parentIdFieldName,String parentIdVal) throws NoSuchFieldException, IllegalAccessException {
        List<Object> rootMenuLists =new  ArrayList<>();
        for(Object obj : menuList) {
            Class clazz = obj.getClass();
            Field pId = clazz.getDeclaredField(parentIdFieldName);
            //打开私有访问
            if (!pId.isAccessible()) {
                pId.setAccessible(true);
            }
            Object value = pId.get(obj);
            if(value.toString().equals(parentIdVal)) {
                rootMenuLists.add(obj);
            }
        }
        return rootMenuLists;
    }
}
